#pragma once

#pragma unmanaged

#pragma managed
#include "..\Entity.h"
#include "EnumType.h"
#include "MethodType.h"
using namespace System::Collections::Generic;

namespace ManagedAPI
{
	public ref class ClassType : public Entity
	{
	public:
		// Instantiates this class, and returns a managed pointer to the new instance.
		// During creation, it caches the UdbEntity pointer in a Dictionary. If the system
		// should ever need to create the identical UdbEntity, it will merely re-use the 
		// previously created copy, and NOT create a new instance of this class. Thus
		// this preserves memory and other resources.
		static ClassType^ Create(const UdbEntity&);
		// Deletes the internal array used to cache all ClassType Entities.
		// This should only be called by the Database::Close(), and NO WHERE else!
		// TODO: Remove this clear method from public exposure.
		static void Clear();
		// Gets all defined and declared methods on a class.
		// A declared method has no definition, and is not used. If it was used, it would generate a linker error.
		// A defined method has a definition, and can be used.
		array<MethodType^>^ GetMethods();
		// Get all member variables defined and declared in this class.
		// Always returns a non null array.
		array<Entity^>^ GetFields();
		// Get all Enums defined in this class.
		// Always returns a non null array.
		array<EnumType^>^ GetEnums();
		// Get all Unions defined in this class.
		// Always returns a non null array.
		array<Entity^>^ GetUnions();
		// Get all immediate classes that this inherits from.
		// It does NOT do this recursively.
		// Always returns a non null array.
		array<ClassType^>^ GetBaseClasses();
		// Get all classes that this inherits from.
		// It does this recursively. Meaning it can return multiple generations of classes.
		// Always returns a non null array.
		array<ClassType^>^ GetAllBaseClasses();
		// Gets classes that immediately inherit from this class.
		// It does NOT do this recursively.
		// Always returns a non null array.
		array<ClassType^>^ GetDerivedClasses();
		// Gets all classes that recursively inherit from this class.
		// It DOES do this recursively.
		// Always returns a non null array.
		array<ClassType^>^ GetAllDerivedClasses();
		// Prints out a string representation of the instance.
		// This is extremely useful for debugging.
		virtual String^ ToString() override;

		// Returns true if this class is immediately defined inside of a class;
		/*	For example:
			class A
			{
				class B {};
				B b;
			};
			In this case, the property would return true; */
		property bool IsDefinedInsideClass { bool get(); }

		//	Returns true if this class is immediately defined inside of a namespace
		/*	namespace A
			{
				class B {};
			}
			In this case, the property would return true; */
		//property bool IsDefinedInsideNamespace { bool get(); }
		
	protected:
		// Protected constructor, use the Create method to instantiate a ClassType.
		// This is only called if the UdbEntity has not been instantiated before.
		ClassType(const UdbEntity&);
	private:

		array<MethodType^>^ mMethodTypes;
		array<Entity^   >^  mFields;
		array<EnumType^ >^  mEnums;
		array<Entity^   >^  mUnions;
		array<ClassType^>^  mBaseClasses;
		array<ClassType^>^  mAllBaseClasses;
		array<ClassType^>^  mDerivedClasses;
		array<ClassType^>^  mAllDerivedClasses;
		void RecurseOperation(ClassType^, List<ClassType^>^, bool);
		//bool IsDefinedIn(String^);

		template<typename T> array<T^>^ GetTypes(String^ refkinds, String^ entkinds);
		static Dictionary<String^, ClassType^>^ mFileList = gcnew Dictionary<String^, ClassType^>();
	};
}